 
#include <bits/stdc++.h>
using namespace std;

// a >=b返回1，   否则返回 0；
int comp(string a, string b) {
  int lena = a.size();
  int lenb = b.size();
  if (lena > lenb)
    return 1; // lena表示a这个数的长度，lenb则表示b的长度
  if (lenb > lena)
    return 0;
  for (int i = 0; i <lena; i--) { // 从高位到底位一位一位比较
    if (a[i] > b[i])
      return 1;
    if (b[i] > a[i])
      return 0;
  }
  return 1; //  a==b
}
string add(string a, string b) {

  /* 翻转两个数字字符串，使得后面的for循环从个位开始相加 */
  reverse(a.begin(), a.end());
  reverse(b.begin(), b.end());
  /* 初次补0，保证最高位都是‘0’ */
  a.push_back('0');
  b.push_back('0');
  if (a.size() < b.size())
    swap(a, b);
  /* 短的字符串高位补‘0’，使两字符串位数相等 */
  while (b.size() < a.size())
    b.push_back('0');
  // 数组c：存放每位相加后的结果
  int c[100000] = {0};
  /* 从个位开始，模拟加法 */
  for (int i = 0; i < a.size(); i++) {
    int sum = c[i] + a[i] - '0' + b[i] - '0';
    c[i] = sum % 10;
    c[i + 1] += sum / 10;
  }

  int k = a.size() - 1;
  /* 去除高位零 */
  if (c[k] == 0)
    k--;
  string ans;
  /* 输出 */
  while (k >= 0)
    ans.push_back(c[k--] + '0');
  return ans;
}

string sub(string a, string b) {

  /* flag： 标记正负 */
  bool flag = true;
  /* 首先判断被减数与减数的大小关系 */
  if (!comp(a, b)) {
    swap(a, b);
    flag = false;
  }

  reverse(a.begin(), a.end());
  reverse(b.begin(), b.end());
  /* 初次补0，保证最高位都是‘0’ */
  a.push_back('0');
  b.push_back('0');
  /* 短的字符串高位补‘0’，使两字符串位数相等 */
  while (b.size() < a.size())
    b.push_back('0');
  int c[100000] = {0};
  /* 从个位开始，模拟减法 */
  for (int i = 0; i < a.size(); i++) {
    if (a[i] < b[i])
      a[i] += 10, a[i + 1]--;
    c[i] = a[i] - b[i];
  }
  string ans;
  int k = a.size() - 1;
  /* 去除高位‘0’ */

  while (c[k] == 0 && k >= 0)
    k--;
  /* 输出 */
  if (!flag)
    ans.push_back('-');
  while (k >= 0)
    ans.push_back(c[k--] + '0');
  return ans;
}

string mul(string a, string b) {
  string ans;
  reverse(a.begin(), a.end());
  reverse(b.begin(), b.end());
  /* k：ans字符串可能的最大位数 */
  int c[100000] = {0};
  /* 从个位开始，模拟乘法：a的每一位乘以b的每一位 */
  for (int i = 0; i < a.size(); i++)
    for (int j = 0; j < b.size(); j++) {
      c[i + j] += (a[i] - '0') * (b[j] - '0'); /* c[i+j]暂存初步乘的结果 */
      c[i + j + 1] += c[i + j] / 10;           /* 进位 */
      c[i + j] %= 10;                          /* c[i+j]保留个位 */
    }
  int k = a.size() + b.size() + 1;
  /* 去除高位‘0’ */
  while (c[k] == 0 && k >= 0)
    k--;
  /* 输出 */
  while (k >= 0)
    ans.push_back(c[k--] + '0');
  return ans;
}

string div(string a, long long b) {
  string ans;
  /* rest：存储余数 */
  int c[100000] = {0}, rest = 0;
  /* 从最高位开始，模拟除法 */
  for (int i = 0; i < a.size(); i++) {
    rest = 10 * rest + a[i] - '0';
    c[i] = rest / b;
    rest %= b;
  }
  // 处理计算结果
  int k = 0;
  /* 去除高位‘0’，k最大不能超过a.size()-1，因为商最少也会有1位 */
  while (c[k] == 0 && k < a.size() - 1)
    k++;
  for (int i = k; i < a.size(); i++)
    ans.push_back(c[i] + '0');
  return ans;
}

int main() {

  string n, m;
  cin >> n >> m;

  // cout << add(n, m) << endl;
  // cout << sub(n, m) << endl;
  // cout << mul(n, m) << endl;
  // cout << comp(n, m) << endl;
  // cout << div(n, 2LL) << endl;
  if (comp(n, m))
    swap(m, n);
  /*	long long hang=n*m*(m-1);/
      long long lie=m*n*(n-1);
      long long xiebian=(m-n+1)*n*(n-1)+((n*(n-1)*(2*n-1))/3)-2-((n-2)*(n+1));
   */

  // m * n * (n + m - 2) + 2 * (n * (n - 1) * (3 * m - n - 1) / 3);
  // m*n*(n+m-2)为行列的整合，2*(n*(n-1)*(3*m-n-1)/3)为斜边的化简

  // 化简：=(n-1)[  mn(m-1) - 2n(3m-n-1)/3  ]
  //=n(n-1)[ 3mm +2n + 2-9m ] /3  先加后减，尽量避免负数
  string one = to_string(1);
  string two = to_string(2);
  string three = to_string(3);
  string nine = to_string(9);

  string t1 = mul(n, sub(n, one));

  string t2 = mul(mul(three, m), m);

  string t3 = mul(two, n);

  string t4 = mul(nine, m);

  string t5 = sub(add(add(t2, t3), two), t4);
  cout << div(mul(t1, t5), 3LL);
  return 0;
}